from google.appengine.ext.webapp import template
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from api_key import handler as api_key_handler
from api_key import get_api_key
import urllib
import logging
import hashlib
import hmac
from google.appengine.api import users
import re
import sys
import traceback

def error(handler, message):
    handler.response.headers['Content-Type'] = 'application/json; charset=utf-8'
    handler.response.set_status(500)
    logging.error(message)
    handler.response.out.write('{ "class" : "%s" }' % message)

def verify_api_sig(request_url, secret_key, api_sig):
    sig = hmac.new(str(secret_key),
                   msg=request_url,
                   digestmod=hashlib.sha1).hexdigest()
    logging.info(str(sig))
    return api_sig == sig

def check_request(request):
    # 0. Read necessary parameters
    api_key = request.get('api_key')
    api_sig = request.get('api_sig')
    api = get_api_key(api_key)
    if not api or not api_sig:
        return False

    # 1. remove api_sig
    """
    request: /hotgirls/random?age=18&api_key=taolao&country=vi
    query_string: age=18&api_key=taolao&country=vi
    [
        (age, 18)
        (api_key, taolao)
        (country, vi)
    ]
    """
    params = dict([x.split('=')
                   for x in request.query_string.split('&')])
    del params['api_sig']

    # 2. sort all parameters (a->z)
    tmp = params.items()
    tmp.sort()

    # 3. rebuild URL request
    query_string = '&'.join([k+'='+urllib.quote(str(v))
                             for (k,v) in tmp])

    # 4. verify signature
    return verify_api_sig(request.path + '?' + query_string,
                   api.secret_key,
                   api_sig)

class HttpServices(webapp.RequestHandler):
    def common(self, handler, method):
        self.response.headers['Content-Type'] = 'application/json; charset=utf-8'
        logging.info('is_admin: %s' % users.is_current_user_admin())
        if ((not check_request(handler.request))
            and (not users.is_current_user_admin())):
            # failed
            error(self, "IncorrectSignatureException")
            return

        # success
        # 1. service = ?, method = ?
        p = re.compile(r'/(\w+)/(\w+)')
        m = p.match(handler.request.path)
        if not m:
            error(self, 'IllegalRequestException')
            return

        service = m.group(1)
        method = m.group(2)

        # 2. find the corresponding service
        # on the server
        module = None
        try:
            module = __import__(service)
        except:
            error(self, 'UndefinedServiceException')
#            exc_type, exc_value, exc_traceback = sys.exc_info()
#            logging.info(repr(traceback.format_exception(
#                                   exc_type,
#                                   exc_value,
#                                   exc_traceback)))
            return

        # 3. dynamic call to service/method
        try:
            getattr(module, method).__call__(handler)
        except:
            error(self, 'InternalServerException' )
#            exc_type, exc_value, exc_traceback = sys.exc_info()
#            logging.info(repr(traceback.format_exception(
#                                   exc_type,
#                                   exc_value,
#                                   exc_traceback)))
            return

    def post(self):
        self.common(self, 'POST')
    def get(self):
        self.common(self, 'GET')

application = webapp.WSGIApplication([
        (r'/api_key/add', api_key_handler.AddApiKey),
        (r'/.*', HttpServices)
], debug=True)


def main():
    run_wsgi_app(application)

if __name__ == "__main__":
    main()